#ifndef MENUSTATE_H
#define MENUSTATE_H

class MenuState;

#include <stdlib.h>
#include <vector>

#include "GameState.h"
#include "GameResources.h"

typedef struct {
	float x;
	float y;
} WinPos;

typedef std::vector<WinPos> PosVector;

/*
 * Base menu class
 */
class MenuState : public GameState
{
    public:
	    MenuState(void) {};
	   ~MenuState(void) {};

        bool pause(void) { exit(); return true; }
        void resume(void) { enter(); }
		virtual bool frameStarted(const Ogre::FrameEvent &evt) { return true; }
        bool frameEnded(const Ogre::FrameEvent &evt);
        
		// Keyboard control functions
	    virtual bool keyPressed(const OIS::KeyEvent &);
        bool keyReleased(const OIS::KeyEvent &);

		// Mouse control functions
        bool mouseMoved(const OIS::MouseEvent &);
        bool mousePressed(const OIS::MouseEvent &, OIS::MouseButtonID);
        bool mouseReleased(const OIS::MouseEvent &, OIS::MouseButtonID);
        CEGUI::MouseButton convertButton(OIS::MouseButtonID buttonID);
        
		// Window subscription functions
        template <class T>
        void subscribeButton(Ogre::String buttonName, 
            bool(T::* f1)(const CEGUI::EventArgs &),
            bool(T::* f2)(const CEGUI::EventArgs &), 
            bool(T::* f3)(const CEGUI::EventArgs &));
        template <class T>
        void subscribeImageButton(Ogre::String buttonName, 
            bool(T::* f1)(const CEGUI::EventArgs &));
        void unsubscribeButton(Ogre::String buttonName);
        void setWindowText(Ogre::String windowName, Ogre::String newText);
		void setWindowColour(Ogre::String windowName, Ogre::String newColour);
        void setWindowImage(Ogre::String windowName, Ogre::String imageName);
        void addEmbeddedWindow(Ogre::String layout);
		
		// Joystick control functions
		void nextButton();
		void prevButton();
		void clickButton();
		void moveMouse();
		void addWinPos(CEGUI::Window *button, bool offsetX);
	
	protected:
		PosVector activeWindows;
		PosVector::iterator winIterator;
};

// This function subscribes a button to a number of events including click, mouse enter and mouse leaves
template <class T>
void MenuState::subscribeButton(Ogre::String buttonName, 
    bool(T::* f1)(const CEGUI::EventArgs &),
    bool(T::* f2)(const CEGUI::EventArgs &),
    bool(T::* f3)(const CEGUI::EventArgs &))
{
    CEGUI::Window *button = (CEGUI::Window*)CEGUI::WindowManager::getSingleton().getWindow(buttonName);
    button->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(f1, (T*)this));
    button->subscribeEvent(CEGUI::PushButton::EventMouseEnters, CEGUI::Event::Subscriber(f2, (T*)this));
    button->subscribeEvent(CEGUI::PushButton::EventMouseLeaves, CEGUI::Event::Subscriber(f3, (T*)this));
	addWinPos(button, true);
}

// This function subscribes an image button to events based on the button being clicked or hovered upon
template <class T>
void MenuState::subscribeImageButton(Ogre::String buttonName, bool(T::* f1)(const CEGUI::EventArgs &))
{	
	CEGUI::Window *imageButton = (CEGUI::Window*)CEGUI::WindowManager::getSingleton().getWindow(buttonName);
    imageButton->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(f1, (T*)this));
	imageButton->subscribeEvent(CEGUI::PushButton::EventMouseEnters, CEGUI::Event::Subscriber(&T::hoverNoise, (T*)this));
	addWinPos(imageButton, true);
}

#endif

